#include "LecteurSymbole.h"
#include <ctype.h>
#include <string.h>
#include <iostream>
using namespace std;

/*! \file LecteurSymbole.cc
    \brief L'implementation du Lecteur de symboles
   
    Définit les méthodes associées à la classe LecteurSymbole
    \author Jamet + Koelsch
    \date 19/12/2012
 */

////////////////////////////////////////////////////////////////////////////////

/*! \fn LecteurSymbole (string nomFich)
    \brief Constructeur de la classe LecteurSymbole
    
    Constructeur de la classe. on lui passe le nom du fichier à 
    interpreter en parametre.
    résultat : symCour = premier symbole du fichier nomFich
    \param nomFich - le nom du fichier à parcourir
*/

LecteurSymbole::LecteurSymbole(string nomFich) :
lc(nomFich), symCour("") {
    suivant(); // pour lire le premier symbole
}

////////////////////////////////////////////////////////////////////////////////

/*! \fn suivant ()
    \brief Passe au symbole suivant du fichier en utilisant sauterCommentaire/Separateurs.
*/
void LecteurSymbole::suivant() {
    sauterSeparateurs();
    // on est maintenant positionne sur le premier caractère d'un symbole
    sauterCommentaire();
    ligne = lc.getLigne();
    colonne = lc.getColonne();
    symCour = Symbole(motSuivant()); // on reconstruit symCour avec le nouveau mot lu
}

////////////////////////////////////////////////////////////////////////////////

/*! \fn sauterSeparateurs()
    \brief Saute une suite de separateurs consecutifs, jusqu'au prochain caractère valide.
*/
void LecteurSymbole::sauterSeparateurs() {
    while (lc.getCarCour() == ' ' ||
            lc.getCarCour() == '\t' ||
            lc.getCarCour() == '\r' ||
            lc.getCarCour() == '\n')
        lc.suivant();
}

////////////////////////////////////////////////////////////////////////////////

/*! \fn motSuivant()
    \brief Lit dans lc la chaine du prochain symbole et la renvoie en resultat

    Lit les caractères jusqu'au prochain mot, lit le symbole suivant et renvoie sa chaine
*/
string LecteurSymbole::motSuivant() {
    static string s;
    s = "";
    bool b = false; // controle virgule / sans virgule
    if (isdigit(lc.getCarCour()))
        // c'est le début d'un entier
        do {
            if (isdigit(lc.getCarCour()))
            {
                s = s + lc.getCarCour();
                lc.suivant();
            }
            else if (lc.getCarCour()=='.' && b == true)
            {
                s = "Erreur, réel avec deux virgules.";
            }
            else if (lc.getCarCour()=='.' && b == false)
            {
                b = true;
                s = s + lc.getCarCour();
                lc.suivant();
            }
        } while (isdigit(lc.getCarCour()) || lc.getCarCour()=='.');

    else if (isalpha(lc.getCarCour()))
        // c'est le début d'un mot
        do {
            s = s + lc.getCarCour();
            lc.suivant();
        } while (isalpha(lc.getCarCour()) ||
                isdigit(lc.getCarCour()) ||
                lc.getCarCour() == '_');

    else if (lc.getCarCour() == '"') {
        do {
            s = s + lc.getCarCour();
            lc.suivant();
            if (lc.getCarCour() == EOF) {
                s = "Erreur, chaîne incomplète";
            }
        } while (lc.getCarCour() != '"' && lc.getCarCour() != EOF);
        s = s + lc.getCarCour();
        lc.suivant();
    }

    else if (lc.getCarCour() == '=') {

        
            s = s + lc.getCarCour();
            lc.suivant();
            if (lc.getCarCour() == '=') {
                s = s + lc.getCarCour();
                lc.suivant();
            }}
            
    else if (lc.getCarCour() == '+') {

        
            s = s + lc.getCarCour();
            lc.suivant();
            if (lc.getCarCour() == '+') {
                s = s + lc.getCarCour();
                lc.suivant();
            }
        
        
    }
    else if (lc.getCarCour() == '-') {

        
            s = s + lc.getCarCour();
            lc.suivant();
            if (lc.getCarCour() == '-') {
                s = s + lc.getCarCour();
                lc.suivant();
            }
        
        
    }
    
    
    else if (lc.getCarCour() == '!') {

        
            s = s + lc.getCarCour();
            lc.suivant();
            if (lc.getCarCour() == '=') {
                s = s + lc.getCarCour();
                lc.suivant();
            }
            else                
                s = "Erreur, problème de symbole";
        
        
    }
    
        else if (lc.getCarCour() == '<') {

        
            s = s + lc.getCarCour();
            lc.suivant();
            if (lc.getCarCour() == '=') {
                s = s + lc.getCarCour(); 
                lc.suivant();
            }
      
       
    }
    
            else if (lc.getCarCour() == '>') {

        
            s = s + lc.getCarCour();
            lc.suivant();
            if (lc.getCarCour() == '=') {
                s = s + lc.getCarCour();    
                lc.suivant();
            }
      
    
    }
    
    else if (lc.getCarCour() != EOF)
        // c'est un caractere special
    {

        s = lc.getCarCour();
        lc.suivant();
    }
    return s;
}
//

////////////////////////////////////////////////////////////////////////////////

/*! \fn sauterCommentaire()
    \brief À partir d'un mot clé (#), saute les tous les caractères jusqu'à '\n'
*/
void LecteurSymbole::sauterCommentaire() {
    while (lc.getCarCour() == '#') {
        while (lc.getCarCour() != '\n') {
            lc.suivant();
        }
        lc.suivant();
        sauterSeparateurs();
    }
}
